package org.example.projecttwo.service.Impl.message;

import org.example.projecttwo.service.Icommon.IRedisService;
import org.example.projecttwo.service.Imessage.IMessageRedisService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.concurrent.TimeUnit;


@Service
public class MessageRedisServiceImpl implements IMessageRedisService {

    private static final Logger logger = LoggerFactory.getLogger(MessageRedisServiceImpl.class);//日志记录器
    private static final String MESSAGE_EXPIRY_KEY_PREFIX = "message:expiry:";//消息的过期键前缀
    private static final String EXPIRY_ZSET_KEY = "message:expirations"; // 存储消息的过期时间

    @Autowired
    private IRedisService redisService;

    /**
     * 使用 Redis Sorted Set存储消息的过期时间
     */
    @Override
    public void setMessageExpiry(Long messageId, Long expireTime) {
        if (messageId == null || expireTime == null) {
            logger.warn("setMessageExpiry参数为空，messageId={},expireTime={}", messageId, expireTime);
            return;
        }
        try {
            //获取当前时间
            long currentTime = System.currentTimeMillis();
            //计算剩余时间
            long remainingTime = expireTime - currentTime;
            if (remainingTime <= 0) {
                logger.info("消息已过期，messageId={}", messageId);
                return;
            }
            //1.设置单个消息的过期键
            String key = MESSAGE_EXPIRY_KEY_PREFIX + messageId;
            redisService.set(key, messageId, remainingTime, TimeUnit.MILLISECONDS);

            //2.将消息的过期时间添加到Sorted Set中
            ZSetOperations<String, Object> zSetOps = redisService.zSetOps();
            zSetOps.add(EXPIRY_ZSET_KEY, messageId, (double) expireTime);
            //设置过期时间，比最晚过期时间+时间长
            redisService.expire(EXPIRY_ZSET_KEY, remainingTime + 10000, TimeUnit.MILLISECONDS);
            logger.info("设置消息的过期时间成功，messageId={},expireTime={}", messageId, expireTime);
        } catch (Exception e) {
            logger.error("设置消息的过期时间失败，messageId={}", messageId, e);
        }
    }

    @Override
    public void removeMessageExpiry(Long messageId) {
        if (messageId == null) {
            return;
        }

        try {
            String key = MESSAGE_EXPIRY_KEY_PREFIX + messageId;
            //1.删除单个消息的过期键
            redisService.delete(key);
            //2.从Sorted Set中删除消息的过期时间
            redisService.zSetOps().remove(EXPIRY_ZSET_KEY, messageId);
            logger.info("移除消息的过期时间成功，messageId={}", messageId);
        } catch (Exception e) {
            logger.error("移除消息的过期时间失败，messageId={}", messageId, e);
        }
    }

    @Override
    public void batchRemoveMessageExpiry(List<Long> messageIds) {
        if (messageIds == null || messageIds.isEmpty()) {
            return;
        }

        try {
            // 1. 批量删除单个消息的过期键
            for (Long messageId : messageIds) {
                String key = MESSAGE_EXPIRY_KEY_PREFIX + messageId;
                redisService.delete(key);
            }

            // 2. 批量从排序集合中移除
            Object[] idArray = messageIds.toArray();
            redisService.zSetOps().remove(EXPIRY_ZSET_KEY, idArray);

            logger.info("批量移除消息过期记录成功，数量={}", messageIds.size());
        } catch (Exception e) {
            logger.error("批量移除消息过期记录失败，数量={}", messageIds.size(), e);
        }
    }
}
